﻿// IPC Library
// Interprocess Communication Library
// Copyright(C)2008 Bill Tudor
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace IPCLibrary
{
	/// <summary>
	/// Mamory Mapped file stream.
	/// </summary>
	/// <remarks>
	/// This method exposes a memory mapped file as a string. This class is internal
	/// to the library. This implementation is exposed as a stream object through the
	/// GetStream() method of the MemoryMappedFile class.
	/// </remarks>
	internal class MemoryMappedFileStream : Stream
	{
		private MemoryMappedFile _fileMapping;
		private long _position;

		public MemoryMappedFileStream(MemoryMappedFile fileMapping)
		{
			_fileMapping = fileMapping;
		}

		public override void Close()
		{
			_fileMapping.Dispose();
			base.Close();
		}
		#region Stream Members

		public override bool CanRead
		{
			get { return true; }
		}

		public override bool CanSeek
		{
			get { return true; }
		}

		public override bool CanWrite
		{
			get { return true; }
		}

		public override void Flush()
		{
			;
		}

		public override long Length
		{
			get { return _fileMapping.Size; }
		}

		public override long Position
		{
			get {return _position;}
			set	{_position = value;}
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			int bytesToRead = count;
			if (bytesToRead + _position > _fileMapping.Size)
			{
				bytesToRead = _fileMapping.Size - (int)_position;
			}
			if (bytesToRead > 0)
			{
				byte[] result = _fileMapping.ReadBytes((int)_position, count);
				_position += count;
				Array.Copy(result, 0, buffer, offset, count);
			}
			return bytesToRead;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			switch (origin)
			{
				case SeekOrigin.Begin:
					_position = offset;
					break;
				case SeekOrigin.Current:
					_position = _position + offset;
					break;
				case SeekOrigin.End:
					_position = _fileMapping.Size - offset;
					break;
			}
			return _position;
		}

		public override void SetLength(long value)
		{
			throw new IPCException("Unable to set length of memory mapped file stream.", new NotImplementedException());
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			_fileMapping.WriteBytes(buffer, offset, (int) _position, count, false);
			_position += count;
		}
		#endregion

	}
}
